package com.zh.oauth.aop;

import com.alibaba.fastjson.JSON;
import com.zh.common.constans.AuthConstant;
import com.zh.common.entity.JSONResult;
import com.zh.oauth.entity.ElecAuth;
import com.zh.oauth.entity.ElecUser;
import com.zh.oauth.service.AuthService;
import com.zh.oauth.service.ElecUserService;
import com.zh.oauth.util.AuthUtil;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * code is far away from bug with the animal protecting
 * ┏┓　　　┏┓
 * ┏┛┻━━━┛┻┓
 * ┃　　　　　　　┃
 * ┃　　　━　　　┃
 * ┃　┳┛　┗┳　┃
 * ┃　　　　　　　┃
 * ┃　　　┻　　　┃
 * ┃　　　　　　　┃
 * ┗━┓　　　┏━┛
 * 　　┃　　　┃神兽保佑
 * 　　┃　　　┃代码无BUG！
 * 　　┃　　　┗━━━┓
 * 　　┃　　　　　　　┣┓
 * 　　┃　　　　　　　┏┛
 * 　　┗┓┓┏━┳┓┏┛
 * 　　　┃┫┫　┃┫┫
 * 　　　┗┻┛　┗┻┛
 *
 * @Description: 权限操作日志记录
 * @Author: Li.HuiNeng
 * @Create in: 2020-06-01 16:29
 * @Version: 1.0.1
 */
@Component
@Aspect
public class AuthLog {

    private static final Logger log = LoggerFactory.getLogger(AuthLog.class);


    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ElecUserService userService;

    @Pointcut("execution(* com.zh.oauth.controller.AuthController.addAuth(..))")
    public void addAuthLog() {
    }

    @Async
    @AfterReturning(value = "addAuthLog()", returning = "result")
    public void afterAddAuth(@NotNull JoinPoint jp, JSONResult result) {
        Map<String, String> map = new HashMap<>();
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        log.info("####### 权限添加记录 #######");
        String uName = String.valueOf(jp.getArgs()[0]);
        ElecAuth auth = (ElecAuth) jp.getArgs()[1];
        String authName = auth.getAuthName();
        String authDes = auth.getAuthDes();
        String authPath = auth.getAuthPath();
        Long pid = auth.getPid();
        Long id = auth.getId();
        // 记录值
        map.put("authName", authName);
        map.put("authDes", authDes);
        map.put("authPath", authPath);
        map.put("pid", String.valueOf(pid));
        map.put("id", String.valueOf(id));
        map.put("des", result.getMessage());
        map.put("notes", apiOperation.notes());
        map.put("success", result.getSuccess() ? "1" : "0");
        String date = String.format("%1$tF %1$tT", new Date());
        map.put("_id", date);
        log.info("操作人：{},目标方法：{}", uName, method.getName());
        mongoTemplate.insert(map, uName + "AUTH");
        if (result.getSuccess()) updateAuthCache(uName);
    }


    @Pointcut("execution(* com.zh.oauth.controller.AuthController.delAuth(..))")
    public void delAuthLog() {
    }

    @Async
    @AfterReturning(value = "delAuthLog()", returning = "result")
    public void afterDelAuth(@NotNull JoinPoint jp, JSONResult result) {
        Map<String, String> map = new HashMap<>();
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        log.info("####### 权限删除记录 #######");
        String uName = String.valueOf(jp.getArgs()[0]);
        ElecAuth auth = (ElecAuth) jp.getArgs()[1];
        String des = auth.getDes();
        Long pid = auth.getPid();
        Long id = auth.getId();
        // 记录值
        map.put("pid", String.valueOf(pid));
        map.put("id", String.valueOf(id));
        map.put("des", result.getMessage());
        map.put("notes", apiOperation.notes());
        map.put("success", result.getSuccess() ? "1" : "0");
        map.put("childrenNotes", des);
        String date = String.format("%1$tF %1$tT", new Date());
        map.put("_id", date);
        log.info("操作人：{},目标方法：{}", uName, method.getName());
        mongoTemplate.insert(map, uName + "AUTH");
        if (result.getSuccess()) updateAuthCache(uName);
    }


    @Pointcut("execution(* com.zh.oauth.controller.AuthController.modAuth(..))")
    public void modAuthLog() {
    }

    @Async
    @AfterReturning(value = "modAuthLog()", returning = "result")
    public void afterModAuth(@NotNull JoinPoint jp, JSONResult result) {
        Map<String, String> map = new HashMap<>();
        MethodSignature methodSignature = (MethodSignature) jp.getSignature();
        Method method = methodSignature.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        log.info("####### 权限修改记录 #######");
        String uName = String.valueOf(jp.getArgs()[0]);
        ElecAuth auth = (ElecAuth) jp.getArgs()[1];
        String authName = auth.getAuthName();
        Long id = auth.getId();
        Long pid = auth.getPid();
        // 记录值
        map.put("authName", authName);
        map.put("id", String.valueOf(id));
        map.put("pid", String.valueOf(pid));
        map.put("notes", apiOperation.notes());
        map.put("success", result.getSuccess() ? "1" : "0");
        String date = String.format("%1$tF %1$tT", new Date());
        map.put("_id", date);
        log.info("操作人：{},目标方法：{}", uName, method.getName());
        mongoTemplate.insert(map, uName + "AUTH");
        if (result.getSuccess()) updateAuthCache(uName);

    }

    /**
     * 更新权限Cache
     *
     * @param uName
     */
    private void updateAuthCache(String uName) {
        log.info("#######更新AUTH缓存数据########");
        ElecUser userInfo = new ElecUser();
        try {
            userInfo = JSON.parseObject(JSON.toJSON(redisTemplate.opsForValue().get(uName + AuthConstant.USER_INFO)).toString(), ElecUser.class);
        } catch (Exception e) {
            log.error("未查询到{}用户的缓存信息", uName);
        }
        List<ElecAuth> authList = userService.selectAuthByUserId(userInfo.getId());
        redisTemplate.opsForValue().set(uName + AuthConstant.REDIS_WEB_SERVE_KEY, AuthUtil.getTreeData(authList));
        log.info("#####操作日志记录完毕####");
    }


}
